<?php

class config implements Observer
{
   private $settings = NULL;
   private $types    = array('string', 'integer', 'numeric', 'email', 'url', 'ip', 'bool', 'json', 'list');

   public function  __construct()
   {
      $this->settings = new stdClass();
      
      $DB = database::getInstance();
      $DB->sql = 'SELECT * FROM `meccano_config` ORDER BY `name` ASC';
      $DB->DB_Fetch();

      for($i=0, $t=$DB->rows; $i<$t; $i++)
      {
         $v            = $DB->fetched[$i];
         $v['value']   = $this->normalizeVariable($v['type'], $v['value']);
         $this->settings->{$v['section'] .'_'. $v['name']} = $v;
      }
      
      
      # MERGE SETTINGS FROM config.inc
      $_SYS_settings = $GLOBALS['_SYS'];
      foreach($_SYS_settings AS $k=>$v)
      {
         $v = array(
            'id'         => NULL,
            'section'    => 'file',
            'name'       => $k,
            'value'      => $v,
            'visability' => 0
         );
         $this->settings->{'file_'. $k} = $v;
      }
      
      $this->settings->{'core_templates'} = array(
         'id'         => NULL,
         'section'    => 'core',
         'name'       => 'templates',
         'value'      => '/templates',
         'visability' => 0
      );
   }
   
   public function notify($msg)
   {
      switch ($msg)
      {
         case signs::S_MODE_ADMIN:
            $this->settings->{'core_templates'} = array(
               'id'         => NULL,
               'section'    => 'core',
               'name'       => 'templates',
               'value'      => '/tpa/templates',
               'visability' => 0
            );
            break;
      }
   }

   public function __get($name)
   {
      $r = NULL;
      $i = 0;
      foreach($this->settings AS $set)
      {
         if($set['name'] == $name)
         {
            $r = $set['value'];
            $i++;
         }
      }

      return $i == 1 ? $r : NULL;
   }

   public function  __call($section, $name = NULL)
   {
      if(isset($name)) $name = reset($name);

      if(isset($name) && property_exists($this->settings, $section .'_'. $name))
      {
         return $this->settings->{$section .'_'. $name}['value'];
      }

      return NULL;
   }

   public function getSettings($level = 2)
   {
      $settings = array();
      foreach($this->settings AS $k=>$v)
      {
         if($v['visability'] >= $level)
         {
            $settings[$k] = $v;
         }
      }

      usort($settings, 'sectionSort');
      return $settings;
   }

   public function getBlocks()
   {
      $settings = $this->getSettings(1);
      $blocks   = array();

      $bl = NULL;
      foreach($settings AS $set)
      {
         if($set['section'] != $bl)
         {
            $bl = $set['section'];
            $blocks[$set['section']] = array(
               'alias'   => $set['section'],
               'enabled' => TRUE
            );
         }

         if($set['name'] == 'enabled' && empty($set['value']))
         {
            $blocks[$set['section']]['enabled'] = FALSE;
         }
      }

      return $blocks;
   }

   public function updateConfig($section, $name, $value)
   {
      $v = $this->settings->{$section .'_'. $name};
      $value = $this->validateConfig($v['type'], $value);
      if($v['value'] != $value)
      {
         $this->settings->{$section .'_'. $name}['value'] = $this->normalizeVariable($v['type'], $value);

         $DB = database::getInstance();
         $DB->DB_QueryBuilder('UPDATE `meccano_config` SET `value` = "%s" WHERE `id` = %i', array($value, $v['id']));
         return $DB->DB_Query();
      }

      return FALSE;
   }

   /**
    * Validate System Config variable
    * @param string $type
    * @param string $value
    * @return string
    */
   private function validateConfig($type, $value)
   {
      $FILTER = new filters();
      if ($type == 'list')
      {
         $value = explode(',', $value);
         $value = $FILTER->filterForAlphaNum($value);
         $value = implode(',', $value);
      } elseif ($type == 'ip')
      {
         $value = explode(',', $value);
         $value = $FILTER->filterForIp($value);
         if(!empty($value)) $value = join(',', $value);
      } elseif ($type == 'json')
      {
         $value = serialize($value);
      } else
      {
         $filter_method = 'isValid' . strtoupper(substr($type, 0, 1)) . strtolower(substr($type, 1));
         if (!$FILTER->$filter_method($value))
         {
            $value = '';
         }
      }

      return $value;
   }


   /**
    * Normilize Value
    *
    * @param string $type
    * @param string $value
    * @return mixed
    */
   private function normalizeVariable($type, $value)
   {
      switch ($type)
      {
         case 'list':
            $value = explode(',', $value);
            break;

         case 'json':
            $value = unserialize($value);
            break;
      }

      return $value;
   }
   

   static public function getInstance()
   {
      static $object_store_singelton;
      if (!is_object($object_store_singelton))
      {
         $object_store_singelton = new config();
      }
      return $object_store_singelton;
   }

   static public function read($name, $section = NULL)
   {
      $_this = config::getInstance();
      if(!empty($section))
      {
         return $_this->{$section}($name);
      } else
      {
         return $_this->{$name};
      }
   }

   static public function write($name, $section, $value)
   {
      $_this = config::getInstance();
      return $_this->updateConfig($section, $name, $value);
   }
}


function sectionSort($a, $b)
{
    return strcmp($a["section"], $b["section"]);
}